<?php
/**
 * 订餐订单model
 */
class RestaurantstyyOrderModel extends BaseModel{

	protected $tableName = 'restaurantstyy_order';

	protected $_link = array(
        'RestaurantOrderGoods' => array(
            'mapping_type' => HAS_MANY,
            'mapping_name' => 'RestaurantOrderGoods',
            'class_name' => 'RestaurantstyyOrderGoods',
            'foreign_key' => 'order_id',
        ),
		'RestaurantInfo' => array(
			'mapping_type' => BELONGS_TO,
			'mapping_name' => 'RestaurantInfo',
			'class_name' => 'RestaurantstyyInfo',
			'foreign_key' => 'restaurant_id',
		),

	);
	//private $accountId = 47;
	private $accountId = 60;
	private $deviceId = '05315700';
    /**
     * curl接口请求
     * @param $reqUrl   请求地址
     * @param $param    请求参数
     * @return mixed
     */
    private function _curlPost($reqUrl, $param)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_POST,1);
        curl_setopt($ch, CURLOPT_HEADER,0);
        curl_setopt($ch, CURLOPT_URL,$reqUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
        $result = json_decode(curl_exec($ch));

        curl_close($ch);

        return $result;
    }

    /**
     * 作用：array转xml
     */
    private function _arrayToXml($array)
    {
        $xml = '<?xml version="1.0"encoding="UTF-8"?>';
        $xml .= '<REQ>';
        foreach ( $array as $key => $val ) {
            $key = strtoupper($key);
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
        }
        $xml .= '</REQ>';

        return $xml;
    }

    /**
     * 将xml转为数组
     * @param string $xml   xml字符串
     * @return mixed
     */
    private function _xmlToArray($xml)
    {
        $reg = "/<(\\w+)[^>]*?>([\\x00-\\xFF]*?)<\\/\\1>/";
        if(preg_match_all($reg, $xml, $matches))
        {
            $count = count($matches[0]);
            $arr = array();
            for($i = 0; $i < $count; $i++)
            {
                $key= $matches[1][$i];
                $val = $this->_xmlToArray( $matches[2][$i] );  // 递归
                if(array_key_exists($key, $arr))
                {
                    if(is_array($arr[$key]))
                    {
                        if(!array_key_exists(0,$arr[$key]))
                        {
                            $arr[$key] = array($arr[$key]);
                        }
                    }else{
                        $arr[$key] = array($arr[$key]);
                    }
                    $arr[$key][] = $val;
                }else{
                    $arr[$key] = $val;
                }
            }
            return $arr;
        }else{
            return $xml;
        }
    }

    /**
     * 创建支付签名
     * @param string $codePayKey 支付密钥
     * @param array $orderInfo 订单信息
     * @return string
     */
    private function _createSign($codePayKey,$orderInfo,$terminalCode)
    {
        $currTimestamp = time();
        $sign = $codePayKey.$terminalCode.$this->accountId. $orderInfo['order_sn'].convertMoneyToFen($orderInfo['order_amount']).$currTimestamp;
        return md5($sign);
    }

    /**
     * 获得支付类型
     * @param string $payCode   支付码
     * @return int
     */
    private function _getPayType($payCode)
    {
        $firstStr = substr($payCode, 0, 1);
        if ($firstStr == 1) {  // 微信
            return 1;
        } elseif ($firstStr == 2) {  // 支付宝
            return 2;
        }
    }

    /**
     * 支付完成回调
     * @param array $payResult 支付结果
     * @param array $orderInfo 订单信息
     */
    private function _payCallBack($payResult, $orderInfo)
    {
        $payResultInfo = $payResult['RET'];
        if(!isset($payResultInfo['STATUS'])) {   //支付异常
            throwException('支付超时，网络异常！', RestaurantPrintError::PAY_SYSTEM_ERROR);
        } elseif($payResultInfo['STATUS'] == '0'){ //明确支付失败
            $errMsg = $payResultInfo['RETURN_MSG'];
            throwException($errMsg,RestaurantPrintError::PAY_SYSTEM_ERROR);
        }
        return array('req_code'=>RestaurantPrintError::OPERATE_SUCCESS, 'message'=>'支付成功!','data'=>$payResultInfo['DATA']);
//         return array('status'=>'S','message'=>'支付成功!','data'=>$payResultInfo['DATA']);
    }

    /**
     * 支付超时回调,撤销订单
     * @param array $resPrintSet 打印配置
     * @param array $orderInfo 订单信息
     */
    private function _payTimeOutCallBack($resPrintSet,$orderInfo)
    {
        $params = array(
            'type' => C('resprint.cancel_refund_type'),
            'account_id' => $this->accountId,
            'device_id' => $this->deviceId,
            'sign' => $this->_createSign($resPrintSet['code_pay_key'],$orderInfo),
            'out_order_sn' => $orderInfo['order_sn'],
            'refund_fee' => convertMoneyToFen($orderInfo['order_amount']),
            'time' => time()
        );
        $codeCancelRefundUrl = $resPrintSet['code_cancel_refund_url'];

        //$params = $this->_arrayToXml($params);
        // 模拟表单提交
        $res = Http::curlPost($codeCancelRefundUrl,$params);

        $lastRes = json_decode($res,true);

        if ($lastRes['status']==1){
            //更新订单信息为退款状态
            $where['order_sn'] = $orderInfo['order_sn'];
            $upData = array(
                'status' => 7,
                'handle' =>1,
                'handle_time' => date('Y-m-d H:i:s')
            );
            $res = $this->_updateOrderInfo($upData,$where);

            if (!$res) {
                throwException('退款状态更新失败!',RestaurantPrintError::PAY_UPDATE_ORDER_FAILED);
            } else {
                return array('req_code'=>RestaurantPrintError::CANCEL_REFUND_SUCCESS, 'message'=>'支付超时,已经将费用退回到您的账户!');
            }
        }else{
            throwException('退款失败!',RestaurantPrintError::CANCEL_REFUND_FAILED);
        }


    }

    /**
     * 更新订单信息
     * @param array $upData    更新数据
     * @param array $where     更新条件
     * @return mixed
     */
    private function _updateOrderInfo($upData, $where)
    {
        $res = $this->where($where)->save($upData);
        return $res;
    }

    /**
     * 添加订单数据入库
     * @param array $postData 订单数据
     * @return bool
     */
    public function addOrderData($postData)
    {
        if (!$postData) {
            throwException('提交的订单数据不能为空!',RestaurantPrintError::SUBMIT_ORDERDATA_EMPTY);
        }

        $condition = array(
            'cut_off' => 0,
            'terminal_code' => $postData['terminal_code']
        );
        $terminalInfo = D('RestaurantstyyPrintTerminal')->getInfo($condition,'name,website_name');

        if ($terminalInfo) {
            $postData['terminal_name'] = $terminalInfo['name'];
            $postData['website_name'] = $terminalInfo['website_name'];
        }

        $payType = $this->_getPayType($postData['pay_code']);
        $postData['pay_type'] = $payType;
        $postData['create_time'] = date('Y-m-d H:i:s');
        $res = $this->add($postData);

        if (!$res) {
            throwException('提交订单失败!',RestaurantPrintError::SUBMIT_ORDER_FAIELD);
        } else {
            return true;
        }
    }

    /**
     * 获得订单信息
     * @param int $orderId 订单编号
     * @return array
     */
    public function getOrderInfo($orderId)
    {
        $condition = array(
            'order_id' => $orderId
        );
        $data = $this->getInfo($condition,'*',null,null,null);
        return $data;
    }

    /**
     * 扫码支付
     * @param array $orderInfo 订单信息
     */
    public function codePay($orderInfo,$accountId,$payCode,$terminalCode)
    {
//         print_r($accountId);exit();
        
        $resPrintSet = D('RestaurantPrintSet')->where(array('account_id'=>$accountId))->find();
       // $resPrintSet = D('RestaurantstyyPrintSet')->where(array('account_id'=>$accountId))->find();
       
        
//         print_r($resPrintSet);exit();
        
        if (!$resPrintSet) {
            throwException('基本配置信息不能为空',1002);
            //throwException('基本配置信息不能为空',RestaurantPrintError::APP_INFO_EMPTY);
        }

//         print_r($orderInfo);exit();
        $payParams = array(
            'type' => 10,//超时50，退款50；
            'account_id' => $accountId,
            'device_id' => $terminalCode,//测试服的post机无卡支付设备id
            'sign' => $this->_createSign($resPrintSet['code_pay_key'],$orderInfo,$terminalCode),
            'total_fee' => convertMoneyToFen($orderInfo['order_amount']),
            'auth_code' => $payCode,
            'out_order_sn' => $orderInfo['order_sn'],
            'time' => time()
        );
//         print_r($payParams);exit();
        $xmlPayParams = $this->_arrayToXml($payParams);
        $codePayUrl = $resPrintSet['code_pay_url'];

        //程序开始执行的时间
        $startTime = microtime(true);
        
        //请求扫码支付接口
        $res = $this->_curlPost($codePayUrl,$xmlPayParams);
        $lastRes = $this->_xmlToArray($res);
        //程序结束计时时间
        $endTime = microtime(true);

        $execTime = $endTime - $startTime;
        $execTimeOut = 60;
        if ($execTime >= $execTimeOut) {    //超时
            //调用撤销订单
            return $this->_payTimeOutCallBack($resPrintSet,$orderInfo);
        } else {    //接口请求成功的操作
            return $this->_payCallBack($lastRes,$orderInfo);
        }
    }

    /**
     * 打印
     * @param $payResult
     * @param $orderInfo
     */
    public function doPrint($payResult,$orderInfo)
    {
        //设置打印内容
        $condition = array(
            'device_id' => $orderInfo['terminal_code'],
            'account_id' => $orderInfo['account_id']
        );
        $cardPayPartner = M('CardPayPartner')->where($condition)->find();

        $content ='|6浙大小乐惠'.'\n'.
            '------------------'.'\n'.
            '|6支付金额:|7' . $orderInfo['order_amount'].'元'.'\n'.
            '|6支付时间:|7' . date('Y-m-d H:i',$payResult['TIME']). '\n'.
            '|5订单号:' . $payResult['OUT_TRADE_NO'].'\n'.
            '网点名:' . $cardPayPartner['address'] . '\n'.
            '终端名:' .$cardPayPartner['terminal_name'] . '\n'.

            '------------------'.'\n'.
            '|6请凭此票到窗口领餐，当日有效'.'\n';

        //获得打印机的设备编号
        $dno = M('RestaurantstyyPrintTerminal')->where(array('terminal_code'=>$orderInfo['terminal_code']))->getField('print_dno');
        $printParams['dno'] = $dno;
        $printParams['content'] = $content;
        $printParams['print_times'] = 1;

        DoPrint::getInstance($printParams)->useWifiPrint();
    }
}